module klang.ir.绑定.IR绑定_;
import 全局;
import std.conv: ·to = to;
import std.functional: ·fd = toDelegate;
import ··诊断_ = klang.编译.诊断.诊断_;
import klang.编译.类型.枚举值.枚举值_: SK, TK;
import klang.编译.诊断集.诊断集_: 诊断集_;
import klang.编译.诊断.诊断_: 诊断_, 诊断消息_;
import klang.编译.类型.类型_: 基础符号_ = 符号_, 绑定子函数_, 绑定函数_, 清理函数_, 文本范围_, 符号表_, 流节点_, 流标志_, 程序主机接口_;
import klang.编译.语法节点.节点_: 源文件_, 节点数组_;
import 基础节点 = klang.编译.语法节点.节点_;
import klang.编译.核心.核心_: 包含, 过滤, 连接, 整数_, 词典_, 循环每个, 开始包含, 创建数组, 克隆词典, 克隆数组, 返回零值;
import klang.编译.工具.工具_: 创建符号表, 创建文件诊断消息;
import klang.编译.路径.路径_: 获取目录路径, 获取基础文件名称, 正规化路径和片段;
import klang.ir.类型.IR类型_: ISK, 符号标志_, 节点标志_, 符号_ = IR符号_, 标识符分类_;
import klang.ir.语法节点.IR节点_: 节点_ = IR节点_, 类型节点_, IR标识符_, IR源文件_, IR文本字面量_, IR数字字面量_, 类型声明_, 结构类型_, 函数定义_, 函数声明_, 全局变量声明_, 别名声明_, 封装声明_, 独立元数据_, 元数据声明_, 特性声明_, 全局摘要声明_, 模块级汇编_, 形参声明_, 局部变量声明_, 块声明_, 冻结指令_, 返回指令_, 直接跳转指令_, 唤出指令_, 值表达式_, 是IR节点, 获取IR节点, 遍历节点, 是局部声明语句;
程序主机接口_ 当前主机;
long NumberedTypes = 0;
long NumberedVals = 0;
long NumberedAttrBuilders = 0;
long 未命名的元数据 = 0;
long 符号数量 = 0;
绑定子函数_ 绑定函数;
IR源文件_ file;
基础节点.节点_ container;
基础节点.节点_ blockScopeContainer;
基础节点.节点_ lastContainer;
流节点_ currentFlow;
流节点_ currentTrueTarget;
流节点_ currentFalseTarget;
流节点_ currentExceptionTarget;
流节点_ preSwitchCaseFlow;
bool hasExplicitReturn = false;
流节点_ unreachableFlow;
流节点_ reportedUnreachableFlow;
流节点_ delegate(流节点_) flowNodeCreated;
static this() {
    unreachableFlow = new 流节点_(流标志_.Unreachable);
    reportedUnreachableFlow = new 流节点_(流标志_.Unreachable);
    flowNodeCreated = .获取初始流函数();
}
enum 容器标志_ : int {
    /** 当前节点不是容器，在重新插入该节点之前不应进行任何容器操作。 */
    无_ = 0,
    /** 当前节点是一个容器。 在重新插入它之前，应将其设置为当前容器（和块容器）。 当前节点没有局部变量。 示例：类、对象字面量、类型字面量、接口... */
    是容器_ = 1,
    /** 当前节点是块作用域容器。 在重新插入它之前，应将其设置为当前块容器。 示例：块（当不受函数养育时）、Catch 子句、for/for in/for 语句... */
    是块范围容器_ = 2,
    /** 当前节点是控制流路径的容器。应保存和恢复当前控制流，并在容器内初始化新的控制流。 */
    是控制流容器_ = 4,
    /** 是函数族 */
    是函数类的_ = 8,
    /** 具有本地 */
    有本地组_ = 32
}
流节点_ initFlowNode(流节点_ n) {
    return n;
}
流节点_ createBranchLabel() {
    return .initFlowNode(new 流节点_(流标志_.BranchLabel));
}
流节点_ createLoopLabel() {
    return .initFlowNode(new 流节点_(流标志_.LoopLabel));
}
流节点_ createReduceLabel(流节点_ target, 流节点_[] antecedents, 流节点_ antecedent) {
    流节点_ n = .initFlowNode(new 流节点_(流标志_.ReduceLabel));
    n.target = target;
    n.antecedents = antecedents;
    n.antecedent = antecedent;
    return n;
}
流节点_ delegate(流节点_) 获取初始流函数() {
    return cast(流节点_ delegate(流节点_))(·fd(&.initFlowNode));
}
void addToContainerChain(基础节点.节点_ next) {
    if (.lastContainer !is ··null!(基础节点.节点_)) {
        lastContainer.下个容器 = next;
    }
    .lastContainer = next;
}
void setFlowNodeReferenced(流节点_ flow) {
    flow.标志 |= ((flow.标志 & 流标志_.Referenced) != 0 ? 流标志_.Shared : 流标志_.Referenced);
}
绑定函数_ 创建绑定工作站(绑定子函数_ 绑定, 程序主机接口_ 主机) {
    .绑定函数 = cast(绑定子函数_)(绑定);
    .当前主机 = 主机;
    return cast(绑定函数_)(·fd(&.绑定工作站));
}
绑定函数_ 创建绑定子工作站() {
    return cast(绑定函数_)(·fd(&.绑定子工作站));
}
清理函数_ 创建绑定清理() {
    return cast(清理函数_)(·fd(&.绑定清理函数));
}
void 绑定子工作站(基础节点.节点_ node) {
    容器标志_ 是容器 = .获取容器标志(node);
    if (是容器 != 容器标志_.无_) {
        .绑定容器节点(node, 是容器);
    }
    else {
        .绑定子节点(node);
    }
}
void 绑定清理函数() {
    .file = 返回零值!(IR源文件_)();
    .container = 返回零值!(基础节点.节点_)();
    .blockScopeContainer = 返回零值!(基础节点.节点_)();
    .lastContainer = 返回零值!(基础节点.节点_)();
    .currentFlow = 返回零值!(流节点_)();
    .currentTrueTarget = 返回零值!(流节点_)();
    .currentFalseTarget = 返回零值!(流节点_)();
    .currentExceptionTarget = 返回零值!(流节点_)();
    .preSwitchCaseFlow = 返回零值!(流节点_)();
    .hasExplicitReturn = false;
}
void 绑定容器节点(基础节点.节点_ node, 容器标志_ 标志) {
    long saveNumberedVals = .NumberedVals;
    基础节点.节点_ saveContainer = .container;
    基础节点.节点_ savedBlockScopeContainer = .blockScopeContainer;
    if ((标志 & 容器标志_.是容器_) != 0) {
        .blockScopeContainer = node;
        .container = .blockScopeContainer;
        if ((标志 & 容器标志_.有本地组_) != 0) {
            node.本地组 = 创建符号表();
        }
        .addToContainerChain(.container);
    }
    if ((标志 & 容器标志_.是函数类的_) != 0) {
        .NumberedVals = 0;
    }
    if ((标志 & 容器标志_.是控制流容器_) != 0) {
        流节点_ delegate(流节点_) saveFlowNodeCreated = cast(流节点_ delegate(流节点_))(.flowNodeCreated);
        流节点_ saveCurrentFlow = .currentFlow;
        bool saveHasExplicitReturn = .hasExplicitReturn;
        流节点_ saveCurrentExceptionTarget = .currentExceptionTarget;
        .currentFlow = .initFlowNode(new 流节点_(流标志_.Start));
        currentFlow.node = node;
        .currentExceptionTarget = ··null!(流节点_);
        .hasExplicitReturn = false;
        .flowNodeCreated = cast(流节点_ delegate(流节点_))(·fd(&.initFlowNode));
        .绑定子节点(node);
        .currentFlow = saveCurrentFlow;
        .currentExceptionTarget = saveCurrentExceptionTarget;
        .hasExplicitReturn = saveHasExplicitReturn;
        .flowNodeCreated = cast(流节点_ delegate(流节点_))(saveFlowNodeCreated);
    }
    else {
        .绑定子节点(node);
    }
    .container = saveContainer;
    .NumberedVals = saveNumberedVals;
    .blockScopeContainer = savedBlockScopeContainer;
}
/** 添加前兆 */
void addAntecedent(流节点_ label, 流节点_ antecedent) {
    if ((antecedent.标志 & 流标志_.Unreachable) == 0 && ((label.antecedents is ··null!(流节点_[])) || !包含!(流节点_)(label.antecedents, antecedent, (流节点_ a, 流节点_ b) { return a == b; }))) {
        if (label.antecedents is ··null!(流节点_[])) {
            label.antecedents = 创建数组!(流节点_)();
        }
        .追加!(流节点_)(label.antecedents, antecedent);
        .setFlowNodeReferenced(antecedent);
    }
}
流节点_ finishFlowLabel(流节点_ flow) {
    流节点_[] antecedents = flow.antecedents;
    if (antecedents is ··null!(流节点_[])) {
        return .unreachableFlow;
    }
    if (antecedents.length == 1) {
        return antecedents[0];
    }
    return flow;
}
容器标志_ 获取容器标志(基础节点.节点_ node) {
    if (node.种类 == SK.源文件) {
        return 容器标志_.是容器_ | 容器标志_.是控制流容器_ | 容器标志_.有本地组_;
    }
    if (!是IR节点(node)) {
        return 容器标志_.无_;
    }
    节点_ n = (cast(节点_)(node));
    switch (n.目标种类) {
        case ISK.函数类型:
        case ISK.函数声明:
        case ISK.函数定义: {
            return 容器标志_.是容器_ | 容器标志_.有本地组_ | 容器标志_.是控制流容器_ | 容器标志_.是函数类的_ | 容器标志_.是块范围容器_;
        }
        default: break;
    }
    return 容器标志_.无_;
}
void setValueDeclaration(符号_ symbol, 节点_ 节点) {
    基础节点.节点_ 值声明 = symbol.值声明;
    if (值声明 is ··null!(基础节点.节点_)) {
        symbol.值声明 = 节点;
    }
}
void 添加符号声明(符号_ 符号, 节点_ 节点, 符号标志_ 标志) {
    符号.标志 |= (cast(整数_)(标志));
    节点.符号 = 符号;
    .setValueDeclaration(符号, 节点);
    if ((标志 & (符号标志_.有成员_)) != 0) {
        符号.成员 = 创建符号表();
    }
}
符号_ 创建符号(符号标志_ 标志, dstring 名称) {
    符号_ 符号 = new 符号_((cast(整数_)(标志)), 名称);
    ++符号数量;
    return 符号;
}
符号_ 声明符号(符号表_ 符号表, 节点_ node, dstring name, 符号_ 父符号 = ··null!(符号_), 符号标志_ 符号标志 = ··null!(符号标志_)) {
    符号_ 符号 = ··null!(符号_);
    if (符号表.具有(name)) {
        .错误(node, 诊断集_.Duplicate_identifier_0, name);
    }
    else {
        符号 = .创建符号(符号标志, name);
        符号表.p·设置(name, 符号);
    }
    .添加符号声明(符号, node, 符号标志);
    if (符号.父符号 !is ··null!(基础符号_)) {
        assert(符号.父符号 == 父符号, "符号的父符号不同错误"c);
    }
    else {
        符号.父符号 = 父符号;
    }
    return 符号;
}
符号_ 声明符号并添加到符号表(节点_ node, dstring name, 符号标志_ 标志) {
    switch (container.目标种类) {
        case ISK.源文件: {
            if ((标志 & 符号标志_.类型声明_) != 0) {
                if ((file.类型组 is null) || (file.类型组.原型 is ··null!(基础符号_[dstring]))) {
                    file.类型组 = 创建符号表();
                }
                return .声明符号(file.类型组, node, name, /*parent*/ ··null!(符号_), 标志);
            }
            if ((标志 & 符号标志_.特性声明_) != 0) {
                if ((file.特性组 is null) || (file.特性组.原型 is ··null!(基础符号_[dstring]))) {
                    file.特性组 = 创建符号表();
                }
                return .声明符号(file.特性组, node, name, /*parent*/ ··null!(符号_), 标志);
            }
            if ((标志 & 符号标志_.封装声明_) != 0) {
                if ((file.封装组 is null) || (file.封装组.原型 is ··null!(基础符号_[dstring]))) {
                    file.封装组 = 创建符号表();
                }
                return .声明符号(file.封装组, node, name, /*parent*/ ··null!(符号_), 标志);
            }
            if ((标志 & (符号标志_.独立元数据_ | 符号标志_.命名元数据_)) != 0) {
                if ((file.元数据 is null) || (file.元数据.原型 is ··null!(基础符号_[dstring]))) {
                    file.元数据 = 创建符号表();
                }
                return .声明符号(file.元数据, node, name, /*parent*/ ··null!(符号_), 标志);
            }
            if ((标志 & 符号标志_.摘要声明_) != 0) {
                if ((file.摘要组 is null) || (file.摘要组.原型 is ··null!(基础符号_[dstring]))) {
                    file.摘要组 = 创建符号表();
                }
                return .声明符号(file.摘要组, node, name, /*parent*/ ··null!(符号_), 标志);
            }
            return .声明符号(file.本地组, node, name, /*parent*/ ··null!(符号_), 标志);
        }
        case ISK.函数类型:
        case ISK.函数定义:
        case ISK.函数声明: {
            return .声明符号(container.本地组, node, name, (cast(符号_)(container.符号)), 标志);
        }
        default: break;
    }
    return ··null!(符号_);
}
void 绑定工作站(基础节点.节点_ node) {
    if (node.种类 == SK.源文件) {
        .file = (cast(IR源文件_)((cast(源文件_)(node))));
        return;
    }
    节点_ nn = 获取IR节点(node);
    if (nn !is ··null!(节点_)) {
        switch (nn.目标种类) {
            case ISK.类型声明: {
                .绑定类型声明((cast(类型声明_)(nn)));
                break;
            }
            case ISK.结构类型: {
                .绑定匿名声明((cast(结构类型_)(nn)));
                break;
            }
            case ISK.函数定义: {
                .绑定函数定义((cast(函数定义_)(nn)));
                break;
            }
            case ISK.函数声明: {
                .绑定函数声明((cast(函数声明_)(nn)));
                break;
            }
            case ISK.全局变量声明: {
                .绑定全局变量声明((cast(全局变量声明_)(nn)));
                break;
            }
            case ISK.别名声明: {
                .绑定别名声明((cast(别名声明_)(nn)));
                break;
            }
            case ISK.封装声明: {
                .绑定封装声明((cast(封装声明_)(nn)));
                break;
            }
            case ISK.独立元数据: {
                .绑定独立元数据((cast(独立元数据_)(nn)));
                break;
            }
            case ISK.元数据声明: {
                .绑定元数据声明((cast(元数据声明_)(nn)));
                break;
            }
            case ISK.特性声明: {
                .绑定特性声明((cast(特性声明_)(nn)));
                break;
            }
            case ISK.全局摘要声明: {
                .绑定全局摘要声明((cast(全局摘要声明_)(nn)));
                break;
            }
            case ISK.模块级汇编: {
                .绑定模块级汇编((cast(模块级汇编_)(nn)));
                break;
            }
            case ISK.形参声明: {
                .绑定形参声明((cast(形参声明_)(nn)));
                break;
            }
            case ISK.局部变量声明: {
                .绑定局部变量声明((cast(局部变量声明_)(nn)));
                break;
            }
            case ISK.块声明: {
                .绑定块声明((cast(块声明_)(nn)));
            }
            default: break;
        }
    }
}
符号_ 绑定匿名声明(结构类型_ n) {
    符号_ 符号 = .创建符号(符号标志_.结构字面量_, "%结构字面量_"d);
    .添加符号声明(符号, n, 符号标志_.结构字面量_);
    return 符号;
}
void 绑定形参声明(形参声明_ n) {
    IR标识符_ name = n.name;
    if (name is ··null!(IR标识符_)) {
        dstring 符号名 = ·to!(dstring)(.NumberedVals);
        ++NumberedVals;
        .声明符号并添加到符号表(n, 符号名, 符号标志_.形参声明_);
        return;
    }
    if ((name.分类 & 标识符分类_.ID标识符_) != 0) {
        dstring 符号名 = name.内容;
        if (name.值 != .NumberedVals) {
            .错误(name, 诊断集_.自动名称_0_增量错误_应该是_1, 符号名, ·to!(dstring)(.NumberedVals));
        }
        ++NumberedVals;
        .声明符号并添加到符号表(n, 符号名, 符号标志_.形参声明_);
    }
    else {
        dstring 符号名 = name.内容;
        .声明符号并添加到符号表(n, 符号名, 符号标志_.形参声明_);
    }
}
void 绑定块声明(块声明_ n) {
    IR标识符_ name = n.name;
    if (name is ··null!(IR标识符_)) {
        dstring 符号名 = ·to!(dstring)(.NumberedVals);
        ++NumberedVals;
        .声明符号并添加到符号表(n, 符号名, 符号标志_.块声明_);
        return;
    }
    if ((name.分类 & 标识符分类_.ID标识符_) != 0) {
        dstring 符号名 = name.内容;
        if (name.值 != .NumberedVals) {
            .错误(name, 诊断集_.自动名称_0_增量错误_应该是_1, 符号名, ·to!(dstring)(.NumberedVals));
        }
        ++NumberedVals;
        .声明符号并添加到符号表(n, 符号名, 符号标志_.块声明_);
    }
    else {
        dstring 符号名 = name.内容;
        .声明符号并添加到符号表(n, 符号名, 符号标志_.块声明_);
    }
}
void 绑定局部变量声明(局部变量声明_ n) {
    IR标识符_ name = n.name;
    if (name is ··null!(IR标识符_)) {
        if (是局部声明语句(n.初始化)) {
            dstring 符号名 = ·to!(dstring)(.NumberedVals);
            ++NumberedVals;
            .声明符号并添加到符号表(n, 符号名, 符号标志_.局部变量_);
        }
        return;
    }
    if ((name.分类 & 标识符分类_.ID标识符_) != 0) {
        dstring 符号名 = name.内容;
        if (name.值 != .NumberedVals) {
            .错误(name, 诊断集_.自动名称_0_增量错误_应该是_1, 符号名, ·to!(dstring)(.NumberedVals));
        }
        ++NumberedVals;
        .声明符号并添加到符号表(n, 符号名, 符号标志_.局部变量_);
    }
    else {
        dstring 符号名 = name.内容;
        .声明符号并添加到符号表(n, 符号名, 符号标志_.局部变量_);
    }
}
void 绑定模块级汇编(模块级汇编_ n) {
    IR文本字面量_ 汇编指令 = (cast(IR文本字面量_)(n.汇编指令));
    dstring 内容 = 汇编指令.内容;
    file.GlobalScopeAsm ~= 内容;
    file.GlobalScopeAsm ~= "\n"d;
}
void 绑定全局摘要声明(全局摘要声明_ n) {
    IR标识符_ name = n.name;
    if ((name.分类 & 标识符分类_.ID标识符_) != 0) {
        dstring 符号名 = name.内容;
        if (name.值 != .NumberedVals) {
            .错误(name, 诊断集_.自动名称_0_增量错误_应该是_1, 符号名, ·to!(dstring)(.NumberedVals));
        }
        ++NumberedVals;
        .声明符号并添加到符号表(n, 符号名, 符号标志_.摘要声明_);
    }
    else {
        assert(false, "全局摘要声明名错误"c);
    }
}
void 绑定特性声明(特性声明_ n) {
    IR标识符_ name = n.name;
    if ((name.分类 & 标识符分类_.ID标识符_) != 0) {
        dstring 符号名 = name.内容;
        if (name.值 != .NumberedAttrBuilders) {
            .错误(name, 诊断集_.自动名称_0_增量错误_应该是_1, 符号名, ·to!(dstring)(.NumberedAttrBuilders));
        }
        ++NumberedAttrBuilders;
        .声明符号并添加到符号表(n, 符号名, 符号标志_.特性声明_);
    }
    else {
        assert(false, "独立元数据名错误"c);
    }
}
void 绑定元数据声明(元数据声明_ n) {
    IR标识符_ name = n.name;
    if ((name.分类 & 标识符分类_.ID标识符_) == 0) {
        dstring 符号名 = name.内容;
        .声明符号并添加到符号表(n, 符号名, 符号标志_.命名元数据_);
    }
    else {
        assert(false, "独立元数据名错误"c);
    }
}
void 绑定独立元数据(独立元数据_ n) {
    IR标识符_ name = n.name;
    if ((name.分类 & 标识符分类_.ID标识符_) != 0) {
        dstring 符号名 = name.内容;
        if (name.值 != .未命名的元数据) {
            .错误(name, 诊断集_.自动名称_0_增量错误_应该是_1, 符号名, ·to!(dstring)(.未命名的元数据));
        }
        ++未命名的元数据;
        .声明符号并添加到符号表(n, 符号名, 符号标志_.独立元数据_);
    }
    else {
        assert(false, "独立元数据名错误"c);
    }
}
void 绑定封装声明(封装声明_ n) {
    IR标识符_ name = n.name;
    if ((name.分类 & 标识符分类_.ID标识符_) == 0) {
        dstring 符号名 = name.内容;
        .声明符号并添加到符号表(n, 符号名, 符号标志_.封装声明_);
    }
    else {
        assert(false, "封装名错误"c);
    }
}
void 绑定别名声明(别名声明_ n) {
    IR标识符_ name = n.name;
    if ((name.分类 & 标识符分类_.ID标识符_) != 0) {
        dstring 符号名 = name.内容;
        if (name.值 != .NumberedVals) {
            .错误(name, 诊断集_.自动名称_0_增量错误_应该是_1, 符号名, ·to!(dstring)(.NumberedVals));
        }
        ++NumberedVals;
        .声明符号并添加到符号表(n, 符号名, 符号标志_.别名声明_);
    }
    else {
        dstring 符号名 = name.内容;
        .声明符号并添加到符号表(n, 符号名, 符号标志_.别名声明_);
    }
}
void 绑定全局变量声明(全局变量声明_ n) {
    IR标识符_ name = n.name;
    if ((name.分类 & 标识符分类_.ID标识符_) != 0) {
        dstring 符号名 = name.内容;
        if (name.值 != .NumberedVals) {
            .错误(name, 诊断集_.自动名称_0_增量错误_应该是_1, 符号名, ·to!(dstring)(.NumberedVals));
        }
        ++NumberedVals;
        .声明符号并添加到符号表(n, 符号名, 符号标志_.全局变量_);
    }
    else {
        dstring 符号名 = name.内容;
        .声明符号并添加到符号表(n, 符号名, 符号标志_.全局变量_);
    }
}
void 绑定函数声明(函数声明_ n) {
    IR标识符_ name = n.name;
    if ((name.分类 & 标识符分类_.ID标识符_) != 0) {
        dstring 符号名 = name.内容;
        if (name.值 != .NumberedVals) {
            .错误(name, 诊断集_.自动名称_0_增量错误_应该是_1, 符号名, ·to!(dstring)(.NumberedVals));
        }
        ++NumberedVals;
        .声明符号并添加到符号表(n, 符号名, 符号标志_.函数定义_);
    }
    else {
        dstring 符号名 = name.内容;
        .声明符号并添加到符号表(n, 符号名, 符号标志_.函数定义_);
    }
}
void 绑定函数定义(函数定义_ n) {
    IR标识符_ name = n.name;
    if ((name.分类 & 标识符分类_.ID标识符_) != 0) {
        dstring 符号名 = name.内容;
        if (name.值 != .NumberedVals) {
            .错误(name, 诊断集_.自动名称_0_增量错误_应该是_1, 符号名, ·to!(dstring)(.NumberedVals));
        }
        ++NumberedVals;
        .声明符号并添加到符号表(n, 符号名, 符号标志_.函数定义_);
    }
    else {
        dstring 符号名 = name.内容;
        .声明符号并添加到符号表(n, 符号名, 符号标志_.函数定义_);
    }
}
void 绑定类型声明(类型声明_ n) {
    IR标识符_ name = n.name;
    if ((name.分类 & 标识符分类_.ID标识符_) != 0) {
        dstring 符号名 = name.内容;
        if (name.值 != .NumberedVals) {
            .错误(name, 诊断集_.自动名称_0_增量错误_应该是_1, 符号名, ·to!(dstring)(.NumberedVals));
        }
        ++NumberedVals;
        .声明符号并添加到符号表(n, 符号名, 符号标志_.类型声明_);
    }
    else {
        dstring 符号名 = name.内容;
        .声明符号并添加到符号表(n, 符号名, 符号标志_.类型声明_);
    }
}
void 绑定子节点(基础节点.节点_ node) {
    if (.checkUnreachable(node)) {
        .绑定每个子节点(node);
        return;
    }
    long k = node.目标种类;
    switch (k) {
        case ISK.源文件: {
            .绑定每个子节点(node);
            (cast(源文件_)(node)).符号数量 = .符号数量;
            return;
        }
        default: break;
    }
    .绑定每个子节点(node);
}
bool 绑定包装(基础节点.节点_ node) {
    .绑定函数(node);
    return false;
}
bool 绑定节点组包装(节点数组_!(基础节点.节点_) nodes) {
    循环每个!(基础节点.节点_, void*)(nodes, (基础节点.节点_ v, size_t i) {
        ((基础节点.节点_ nn, size_t _) { return .绑定函数(nn); })(v, i);
        return null;
    });
    return false;
}
void 绑定每个子节点(基础节点.节点_ node) {
    遍历节点(node, cast(bool delegate(基础节点.节点_))(·fd(&.绑定包装)), cast(bool delegate(节点数组_!(基础节点.节点_)))(·fd(&.绑定节点组包装)));
}
bool checkUnreachable(基础节点.节点_ node) {
    if ((currentFlow.标志 & 流标志_.Unreachable) == 0) {
        return false;
    }
    if (.currentFlow == .unreachableFlow) {
        .currentFlow = .reportedUnreachableFlow;
        .eachUnreachableRange(node, cast(void delegate(基础节点.节点_, 基础节点.节点_))(·fd(&.报告错误)));
    }
    return true;
}
void 报告错误(基础节点.节点_ start, 基础节点.节点_ end) {
    文本范围_ n = new 文本范围_();
    n.开始 = start.开始;
    n.结束 = end.结束;
    .错误(n, 诊断集_.Unreachable_code_detected, ""d);
}
void 错误(文本范围_ node, 诊断消息_ message, dstring arg0 = ··null!(dstring), dstring arg1 = ··null!(dstring), dstring arg2 = ··null!(dstring)) {
    if (file.绑定诊断 is ··null!(诊断_[])) {
        file.绑定诊断 = 创建数组!(诊断_)();
    }
    ··诊断_.诊断包括位置_ 消息 = 创建文件诊断消息(.file, node.开始, node.结束 - node.开始, message, [arg0, arg1, arg2]);
    .追加!(诊断_)(file.绑定诊断, 消息);
}
void eachUnreachableRange(基础节点.节点_ node, void delegate(基础节点.节点_, 基础节点.节点_) cb) {
    cb(node, node);
}
